package com.twp.auth.service.manage;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.twp.auth.domain.authority.Menu;
import com.twp.auth.domain.authority.Role;
import com.twp.auth.domain.authority.user.ManageUser;
import com.twp.auth.repository.auth.MenuRepository;
import com.twp.auth.repository.auth.RoleRepository;
import com.twp.auth.repository.user.ManageUserRepository;
import com.twp.auth.rest.api.manage.RoleControler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.criteria.Predicate;
import java.security.Principal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class RoleService {

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    MenuRepository menuRepository;

    @Autowired
    ManageUserRepository manageUserRepository;

    @Autowired
    EntityManager entityManager;

    public Page<Role> find(Role role, Pageable pageable){
        return roleRepository.findAll(
                (root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> predicates = new ArrayList<>();
                    if(!StringUtils.isEmpty(role.getId())){
                        predicates.add(criteriaBuilder.equal(root.get("id"),role.getId()));
                    }
                    if(!StringUtils.isEmpty(role.getRoleName())){
                        predicates.add(criteriaBuilder.like(root.get("roleName"), "%"+role.getRoleName()+"%"));
                    }
                    if(!StringUtils.isEmpty(role.getRoleCode())){
                        predicates.add(criteriaBuilder.like(root.get("roleCode"), "%"+role.getRoleCode()+"%"));
                    }
                    return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
                },
                pageable);
    }

    public List<Role> queryRolesByUid(Integer uId){
        return roleRepository.queryRolesByUid(uId);
    }

    public void deleteById(Integer id){
        roleRepository.delete(id);
    }

    public void saveOrUpdate(Role role){
        Date d = new Date();
        if (role.getId()==null) role.setCreateTime(d);
        role.setUpdateTime(d);
        entityManager.merge(role);
    }

    /*
    此处是否做增量更新menu
    前端提供所有menuId，后端增量更新
     */
    public void action(RoleControler.ActionBody actionBody){
        Date d = new Date();
        /*
        此处需要做差集(delete),补集(add),
        因为集合的一次性操作，使用java层做会非常容易，所以借助jpa的关联
         */
        Role role = roleRepository.findOne(actionBody.getRoleId());
        if (role!=null){
            List<Menu> menuList = menuRepository.findAll(actionBody.getMenuIds());
            role.setMenuList(new HashSet<>(menuList));
            roleRepository.save(role);
        }
//        Optional.ofNullable(role)
//                .ifPresent(
//                        r->{
//                            List<Menu> menuList = r.getMenuList();
//
//                            List<Integer> oldMenuIds = menuList.stream().map(m->m.getId()).collect(Collectors.toList());
//
//                            List<Integer> newMenuIds = actionBody.getMenuIds();
//
//                            /*
//                            差集
//                             */
//                             List<Integer> diff = Lists.newArrayList(Sets.difference(Sets.newHashSet(newMenuIds), Sets.newHashSet(oldMenuIds)));
//                            /*
//                            补集
//                            1.先求交集
//                            2.newMenuIds 与交集的差集就是补集
//                             */
//                            Set<Integer> intersection  = Sets.intersection(Sets.newHashSet(newMenuIds), Sets.newHashSet(oldMenuIds));
//
//                            List<Integer> supplementary = Lists.newArrayList(Sets.difference(Sets.newHashSet(newMenuIds), Sets.newHashSet(intersection)));
//                            //action(menuList,diff,supplementary,actionBody.getRoleId());
//                        }
//                );

    }
    //做更新操作
    //此处为了事物的完整
//    public void action(List<Menu> menuList,List<Integer> diff,List<Integer> supplementary,Integer roleId){
//        if(!diff.isEmpty()){
//            //roleRepository.deleteByDiff(diff);
//            menuList.stream().filter(
//
//            )
//        }
//        if (!supplementary.isEmpty()){
//            List<Menu> menuList = menuRepository.findAll(supplementary);
//
//            roleRepository.save(
//                    roleMenus
//            );
//        }
//    }

    public Page<Role> loadData(Integer userId,String roleName,String roleCode, Pageable pageable){
        // 获取所有可用角色
        Page<Role> roleList = roleRepository.findAll(
                (root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> predicates=new ArrayList<>();
                    if (!StringUtils.isEmpty(roleName)){
                        predicates.add(criteriaBuilder.equal(root.get("roleName"), roleName));
                    }
                    if (!StringUtils.isEmpty(roleCode)){
                        predicates.add(criteriaBuilder.equal(root.get("roleCode"), roleCode));
                    }
                    predicates.add(criteriaBuilder.equal(root.get("status"), 1));
                    return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
                },
                pageable
                );
        ManageUser manageUser = manageUserRepository.findAllByIdAndStatus(userId,1);

        List<Role> userRoleList = manageUser.getRoleList();
        if (!roleList.getContent().isEmpty()&&(!userRoleList.isEmpty())){
           // 求出交集，并设置checked为true
           for (Role role:roleList.getContent()){
               for (Role userRole: userRoleList){
                   if (role.getId().equals(userRole.getId())){
                       role.set_checked(true);
                       break;
                   }
               }
           }
        }
        return roleList;
    }
}
